/*
 * eID Test PKI Project.
 * Copyright (C) 2012 FedICT.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 3.0 as published by the Free Software Foundation.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, see 
 * http://www.gnu.org/licenses/.
 */

package be.fedict.eid.pki.model;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.ConcurrencyManagementType;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Singleton;
import javax.ejb.Startup;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

@Singleton
@Startup
@ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class StorageBean {

	private static final Log LOG = LogFactory.getLog(StorageBean.class);

	private Map<String, File> files;

	@PostConstruct
	public void startup() {
		LOG.debug("startup");
		this.files = new ConcurrentHashMap<String, File>();
	}

	@PreDestroy
	public void shutdown() {
		LOG.debug("shutdown");
		for (Map.Entry<String, File> fileEntry : this.files.entrySet()) {
			String resourceName = fileEntry.getKey();
			File resourceFile = fileEntry.getValue();
			LOG.debug("removing resource: " + resourceName);
			if (!resourceFile.delete()) {
				LOG.warn("could not delete file: "
						+ resourceFile.getAbsolutePath());
			}
		}
	}

	@Lock(LockType.WRITE)
	public void store(String resourceName, byte[] data) {
		File existingFile = this.files.get(resourceName);
		if (null != existingFile) {
			if (!existingFile.delete()) {
				LOG.warn("could not delete file: "
						+ existingFile.getAbsolutePath());
			}
		}
		File tmpFile;
		try {
			tmpFile = File.createTempFile(resourceName + "-", ".dat");
			FileUtils.writeByteArrayToFile(tmpFile, data);
		} catch (IOException e) {
			LOG.error("IO error: " + e.getMessage(), e);
			this.files.remove(resourceName);
			return;
		}
		LOG.debug("storing " + resourceName + " @ " + tmpFile.getAbsolutePath());
		this.files.put(resourceName, tmpFile);
	}

	@Lock(LockType.READ)
	public InputStream getInputStream(String resourceName) {
		File file = this.files.get(resourceName);
		FileInputStream fileInputStream;
		try {
			fileInputStream = new FileInputStream(file);
		} catch (FileNotFoundException e) {
			throw new RuntimeException();
		}
		return fileInputStream;
	}

	@Lock(LockType.WRITE)
	public void remove(String resourceName) {
		File existingFile = this.files.get(resourceName);
		if (null != existingFile) {
			if (!existingFile.delete()) {
				LOG.warn("could not delete file: "
						+ existingFile.getAbsolutePath());
			}
		}
		this.files.remove(resourceName);
	}
}
